vimfandomcom-20200223-history
Calculator Editing
This tip adds a good calculator to Vim visual mode selections. It allows you to replace a block of math expressions by their calculated results. Add the following lines to your vimrc. function MyCalc(str) if exists("g:MyCalcRounding") return system("echo 'x=" . a:str . ";d=.5/10^" . g:MyCalcPresition \. ";if (x<0) d=-d; x+=d; scale=" . g:MyCalcPresition . ";print x/1' | bc -l") else return system("echo 'scale=" . g:MyCalcPresition . " ; print " . a:str . "' | bc -l") endif endfunction " Control the precision with this variable let g:MyCalcPresition = 2 " Comment this if you don't want rounding let g:MyCalcRounding = 1 " Use \C to replace the current line of math expression(s) by the value of the computation: map c :s/.*/\=MyCalc(submatch(0))/:noh " Same for a visual selection block vmap c :B s/.*/\=MyCalc(submatch(0))/:noh " With \C= don't replace, but add the result at the end of the current line map c= :s/.*/\=submatch(0) . " = " . MyCalc(submatch(0))/:noh " Same for a visual selection block vmap c= :B s/.*/\=submatch(0) . " = " . MyCalc(submatch(0))/:noh " Try: :B s/.*/\=MyCalc("1000 - " . submatch(0))/ " The concatenation is important, since otherwise it will try " to evaluate things like in ":echo 1000 - ' 1748.24'" vmap c+ :B s/.*/\=MyCalc(' +' . submatch(0))/ vmap c- :B s/.*/\=MyCalc(' -' . submatch(0))/ " With \Cs you add a block of expressions, whose result appears in the command line vmap ct y:echo MyCalc(substitute(@0," *\n","+","g")):silent :noh " Try: :MyCalc 12.7 + sqrt(98) command! -nargs=+ MyCalc :echo MyCalc("") Usage As a visual block calculator 1. First, visually select a (block of) math expression(s). Example: "12.7 + sqrt(98.7)" (without the quotes). Then type ether \C or \C= With \C the formula will be replaced by its result from bc ("22.63" in the example). With \C= the formula will remain, but the result will be appended ("12.7 + sqrt(98.7) = 22.63" in the example). 2. First, visually select a (block of) math expression(s). Example: "sqrt(98.7)". Then type: :B s/.*/\=MyCalc("12.7 + " . submatch(0))/ The expression will be replaced by its result ("22.63" in the example). The marks '<,'> will appear behind the "B", but that is fine (block marks). This is useful if you want to, say, add "12.7" to a (column of) number(s). The numbers do not have to be integers. Both methods work for block of expressions. So, if you visually select the block: 12.7 + sqrt(98.7) 57 + 12 88 1 0 3*4 12 s(4) and type \C you will have the block replaced with: 22.63 69 88 0 1 -.75 Using bc, 's()' is the sine function. As a command line calculator 3. In normal mode, type :MyCalc 12.7 + sqrt(98.7) You will get "22.63" in the command line. This usage mode is similar to VimTip1235, but doesn't need embedded python. Requirements It uses , and the Unix/Linux command line calculator 'bc'. Do a 'man bc' in the shell to know its built-in functions, like 's()' above. You can easily replace 'bc' by your favorite calculator program. The precision of the calculator is controlled by the variable g:MyCalcPresition. References * * * Comments With this map you can add a block of expressions, and the result will appear in the command line: vmap Cs y:echo MyCalc(substitute(@0," *\n","+","g")) ---- " I've added the code for Windows. This has been checked " for the shells cmd and 4nt. " " For rounding, the '^' operator, to raise a number to an " integer power, happens to be the escape character for " these shells. Because of the odd escaping required in " CMD, a separate return is needed for CMD vs 4NT. There " is no difference for the non-rounding return. " " You can enter "2^10" for 2 to the power 10. let g:MyCalcPrecision = 2 let g:MyCalcRounding = 1 function MyCalc(str) if exists("g:MyCalcRounding") if has("win32") if &shell =~? "cmd\.exe" let s:str = substitute(a:str,'\^','^^^^','g') return system("echo x=".s:str.";d=.5/10^^^^".g:MyCalcPrecision \.";if(x^^^<0)d=-d;x+=d;scale=".g:MyCalcPrecision.";print x/1|bc -l") else let s:str = substitute(a:str,'\^','^^','g') return system("echo x=".s:str.";d=.5/10^^".g:MyCalcPrecision \.";if(x^<0)d=-d;x+=d;scale=".g:MyCalcPrecision.";print x/1|bc -l") endif else return system("echo 'x=" . a:str . ";d=.5/10^" . g:MyCalcPrecision \.";if (x<0) d=-d; x+=d; scale=" . g:MyCalcPrecision \. ";print x/1' | bc -l") endif else if has("win32") if &shell =~? "cmd\.exe" let s:str = substitute(a:str,'\^','^^^^','g') else let s:str = substitute(a:str,'\^','^^','g') endif return system("echo x=".s:str.";scale=".g:MyCalcPrecision \.";print x/1|bc -l") else return system("echo 'scale=" . g:MyCalcPrecision \. " ; print " . a:str . "' | bc -l") endif endif endfunction See . ----